/*
 *  Copyright (c) 2010 Mathew Hall.
 *  All rights reserved.
 * 
 *  Redistribution and use in source and binary forms, with or
 *  without modification, are permitted provided that the following conditions
 *  are met:
 * 
 *  Redistributions of source code must retain the above copyright
 *  notice, this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above
 *  copyright notice, this list of conditions and the following
 *  disclaimer in the documentation and/or other materials provided
 *  with the distribution.
 *  Neither the name of the University of Sheffield nor the names of its
 *  contributors may be used to endorse or promote products derived
 *  from this software without specific prior written permission.
 * 
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 *  CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 *  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 *  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
 *  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 *  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 *  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 *  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package main;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.ObjectOutputStream;

import search.util.SearchResult;
import translator.DOTWriter;
import translator.SILWriter;

/**
 *
 * @author Mathew Hall
 */
public class Experiment {

    private File inputname, siloutpath, dotoutpath, fitnessoutpath, clusteroutpath, evaluationoutpath;
    private String fitnessFunction;
    private String geneType;
    private String experimentName;
    private String searchType;

	private int fitnessBudget;

    public String getSearchType() {
        return searchType;
    }

    public void setSearchType(String searchType) {
        this.searchType = searchType;
    }
    
    public void setExperimentName(String n){
        experimentName = n;
    }	
    public String getExperimentName(){
        return experimentName;
    }

    public void setGeneType(String gt){
        geneType = gt;
    }

    public String getGeneType(){
        return geneType;
    }

    private int numThreads = 1;

    public int getNumThreads() {
        return numThreads;
    }

    public void setNumThreads(int numThreads) {
        this.numThreads = numThreads;
    }
    Experiment(File input, String fitness, int numThreads) {
        this(input,fitness);
        this.numThreads = numThreads;
    }

	public int getFitnessBudget(){
		return fitnessBudget;
	}

	public void setFitnessBudget(int fb){
		fitnessBudget = fb;
	}

    public int getChromesize() {
        return chromesize;
    }

    public File getClusteroutpath() {
        return clusteroutpath;
    }

    public File getDotoutpath() {
        return dotoutpath;
    }

    public String getFitnessFunction() {
        return fitnessFunction;
    }

    public File getFitnessoutpath() {
        return fitnessoutpath;
    }

    public File getEvaluationoutpath() {
        return evaluationoutpath;
    }


    public File getInputname() {
        return inputname;
    }

    public int getNumgens() {
        return numgens;
    }

    public void setChromesize(int chromesize) {
        this.chromesize = chromesize;
    }

    public void setClusteroutpath(File clusteroutpath) {
        this.clusteroutpath = clusteroutpath;
    }

    public void setDotoutpath(File dotoutpath) {
        this.dotoutpath = dotoutpath;
    }

    public void setFitnessoutpath(File fitnessoutpath) {
        this.fitnessoutpath = fitnessoutpath;
    }


    public void setEvaluationoutputpath(File evaluationoutpath) {
        this.evaluationoutpath = evaluationoutpath;
    }
    

    public void setNumgens(int numgens) {
        this.numgens = numgens;
    }

    public void setPopsize(int popsize) {
        this.popsize = popsize;
    }

    public void setSiloutpath(File siloutpath) {
        this.siloutpath = siloutpath;
    }

    public int getPopsize() {
        return popsize;
    }

    public SearchResult getResults() {
        return results;
    }

    public File getSiloutpath() {
        return siloutpath;
    }
    private int popsize, chromesize, numgens;
    private SearchResult results;

    public void setResult(SearchResult r) {
        results = r;
    }

    public Experiment(File inputname, String fitnessFunction, File siloutpath, File dotoutpath, File fitnessoutpath, File clusteroutpath) {
        this.inputname = inputname;
        this.siloutpath = siloutpath;
        this.dotoutpath = dotoutpath;
        this.fitnessoutpath = fitnessoutpath;
        this.clusteroutpath = clusteroutpath;
        this.fitnessFunction = fitnessFunction;
    }

    public Experiment(File inputname, String fitnessFunction, File siloutpath, File dotoutpath, File fitnessoutpath, File clusteroutpath, int popsize, int chromesize, int numgens) {
        this.inputname = inputname;
        this.siloutpath = siloutpath;
        this.dotoutpath = dotoutpath;
        this.fitnessoutpath = fitnessoutpath;
        this.clusteroutpath = clusteroutpath;
        this.fitnessFunction = fitnessFunction;
        this.popsize = popsize;
        this.chromesize = chromesize;
        this.numgens = numgens;
    }

    public Experiment(File inputname, String fitnessFunction) {
        this.inputname = inputname;
        this.fitnessFunction = fitnessFunction;
    }

    public Experiment(File inputname, String fitnessFunction, File siloutpath, File dotoutpath, File fitnessoutpath) {
        this.inputname = inputname;
        this.siloutpath = siloutpath;
        this.dotoutpath = dotoutpath;
        this.fitnessoutpath = fitnessoutpath;
        this.fitnessFunction = fitnessFunction;
    }

    public boolean hasRun() {
        return results == null;
    }

    public void storeAll() throws IOException, ExperimentNotRunException {
        if (results == null) {
            throw new ExperimentNotRunException();
        }
        if (siloutpath != null) {
            if (!siloutpath.exists()) {
                siloutpath.getParentFile().mkdirs();
                siloutpath.createNewFile();
            }
            FileWriter fstream = new FileWriter(siloutpath);
            BufferedWriter out = new BufferedWriter(fstream);
            out.write(SILWriter.getSIL(results.getClustering()));
            out.close();
        }

        if (dotoutpath != null) {
            if (!dotoutpath.exists()) {
                dotoutpath.getParentFile().mkdirs();
                dotoutpath.createNewFile();

            }
            FileWriter fstream = new FileWriter(dotoutpath);
            BufferedWriter out = new BufferedWriter(fstream);
			
			

            out.write(new DOTWriter().getDOT(results.getClustering(),results.getProgram()));
            out.close();
        }
        if (fitnessoutpath != null) {
            if (!fitnessoutpath.exists()) {
                fitnessoutpath.getParentFile().mkdirs();
                fitnessoutpath.createNewFile();

            }
            FileWriter fstream = new FileWriter(fitnessoutpath);
            BufferedWriter out = new BufferedWriter(fstream);
            out.write(Double.toString(results.getFitnessValue()));
            out.close();
        }
        if (clusteroutpath != null) {
            if (!clusteroutpath.exists()) {
                clusteroutpath.getParentFile().mkdirs();
                clusteroutpath.createNewFile();
            }
            FileOutputStream fos = null;
            ObjectOutputStream out = null;
            fos = new FileOutputStream(clusteroutpath);
            out = new ObjectOutputStream(fos);
            out.writeObject(results.getClustering());
            out.close();

        }
        if (evaluationoutpath != null) {
            if (!evaluationoutpath.exists()) {
                evaluationoutpath.getParentFile().mkdirs();
                evaluationoutpath.createNewFile();

            }
            FileWriter fstream = new FileWriter(evaluationoutpath);
            BufferedWriter out = new BufferedWriter(fstream);
            out.write(Integer.toString(results.getFitnessEvaluations()));
            out.close();
        }
    }
}
